package com.tzbank.wisdom.utils;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;


/**
 * 
 * @author zhujf
 * 
 */
public class Util {
	private static Log log = LogFactory.getLog(Util.class);

	public static int MAX_RECORD_COUNT = 2000;
	public static String MAX_RECORD_COUNT_MSG = " 2000 ";
	public static boolean isNullOrEmpty(String inStr) {
		return (inStr == null || inStr.trim().length() == 0);
	}

	/**
	 * 根据当前日期计算出与当前日期间隔时间单位的日期
	 * 
	 * @param currentDate
	 *            当前日期
	 * @param dateUnit
	 *            时间单位
	 * @param prev
	 *            前滚标志
	 * @param dateUnitType
	 *            滚动日期单位的类型
	 * @return
	 */
	public static Date rollDateByDateUnit(Date currentDate, int dateUnit,
			int dateUnitType) {
		Calendar calendar = GregorianCalendar.getInstance(Locale.getDefault());
		if (currentDate != null) {
			calendar.setTime(currentDate);
		}
		calendar.add(dateUnitType, dateUnit);
		return new Date(calendar.getTime().getTime());
	}

	/**
	 * 根据当前日期计算出与当前日期间隔天数的日期
	 * 
	 * @param dateTime
	 * @param value
	 * @return
	 */
	public static Date rollDateByDay(Date currentDate, int day) {
		Calendar calendar = GregorianCalendar.getInstance(Locale.getDefault());
		if (currentDate != null) {
			calendar.setTime(currentDate);
		}
		calendar.add(Calendar.DATE, day);
		return new Date(calendar.getTime().getTime());
	}

	public static Date rollDateByWeek(Date currentDate, int week) {
		Calendar calendar = GregorianCalendar.getInstance(Locale.getDefault());
		if (currentDate != null) {
			calendar.setTime(currentDate);
		}
		calendar.add(Calendar.WEDNESDAY, week);
		return new Date(calendar.getTime().getTime());
	}

	public static Date rollDateByMonth(Date currentDate, int month) {
		Calendar calendar = GregorianCalendar.getInstance(Locale.getDefault());
		if (currentDate != null) {
			calendar.setTime(currentDate);
		}
		calendar.add(Calendar.MONTH, month);
		return new Date(calendar.getTime().getTime());
	}

	public static Date rollDateByYear(Date currentDate, int year) {
		Calendar calendar = GregorianCalendar.getInstance(Locale.getDefault());
		if (currentDate != null) {
			calendar.setTime(currentDate);
		}
		calendar.add(Calendar.YEAR, year);
		return new Date(calendar.getTime().getTime());
	}

	public static Date toDate(int year, int month, int day) {
		return toDate(year, month, day, 0, 0, 0);
	}

	public static Date toDate(int year, int month, int day, int hour,
			int minute, int second) {
		Calendar c = Calendar.getInstance();
		c.set(year, month - 1, day, hour, minute, second);
		return new Date(c.getTimeInMillis());
	}

	private static int toDays(Date date) {
		int dayOffset = -1;
		Calendar c = Calendar.getInstance();
		Calendar timeZero = Calendar.getInstance();
		timeZero.setTimeInMillis(0);
		c.setTime(date);

		while (timeZero.get(Calendar.YEAR) < c.get(Calendar.YEAR)) {
			dayOffset += timeZero.getActualMaximum(Calendar.DAY_OF_YEAR);
			timeZero.add(Calendar.YEAR, 1);
		}

		dayOffset += c.get(Calendar.DAY_OF_YEAR);
		return dayOffset;
	}

	public int differByDay(Date date1, Date date2) {
		return (int) (toDays(date1) - toDays(date2));
	}



	
	public static boolean isBoolean(String s) {
		if (("Y").equals(s) || (("Yes").equals(s))) {
			return true;
		}
		return false;
	}



	public static int resovleDateUnit(String unit) {
		if (unit.equals(DAY)) {
			return Calendar.DATE;
		} else if (unit.endsWith(MONTH)) {
			return Calendar.MONTH;
		} else if (unit.endsWith(YEAR)) {
			return Calendar.YEAR;
		} else if (unit.endsWith(WEEK)) {
			return Calendar.WEEK_OF_YEAR;
		} else {
			throw new IllegalArgumentException("invalid data parameter " + unit);
		}
	}

	private final static String DAY = "D";
	private final static String MONTH = "M";
	private final static String YEAR = "Y";
	private final static String WEEK = "W";

	
	/**
	 * 将BASE64编码的字符串进行解析为原始数据对象
	 * 
	 * @param encodeBase64
	 * @return
	 */
	public static Object decoderBASE64ToString(String encoderBase64) {
		return null;
		// return new String(Base64.base64ToByteArray(encoderBase64));
	}

	/**
	 * 将string格式的日期按照指定的日期格式转换成date类型
	 */
	public static java.util.Date parseDate(String dateString, String pattern) {
		SimpleDateFormat simpledateformat = new SimpleDateFormat(pattern);
		try {
			return (java.util.Date) simpledateformat.parse(dateString);
		} catch (ParseException e) {
			throw new IllegalArgumentException(e.getMessage());
		}
	}

	public static boolean equals(Object obj, Object anObject) {
		boolean bool = false;
		if (obj == null || anObject == null) {
			return bool;
		}

		bool = obj.equals(anObject);
		return bool;
	}

	/**
	 * 开通的认证类型:1表示开通,0表示关闭.AuthenticateType:000000 表示:第一位表示交易密码认证 第二位渠道密码认证
	 * 第三位证书认证 第四表示动态口令认证 第五位表示交易短信认证 第六位表示支付密码认证
	 */
	public final static String AuthenticateTypeMapping = "TECOSP";

	/**
	 * 身份证18位转15位
	 * 
	 * @author guojie
	 * 
	 * @param idNo
	 * @return String
	 */
	public static String convertIdNoToShort(String idNo) {
		if (idNo.length() != 18) {
			return "";
		}
		// 去除年份前2位，和最后一位
		return idNo.substring(0, 6) + idNo.substring(8, 17);
	}

	/**
	 * 身份证15位转18位
	 * 
	 * @author guojie
	 * 
	 * @param idNo
	 * @return String
	 */
	public static String convertIdNoToLong(String idNo) {
		if (idNo.length() != 15) {
			return "";
		}
		idNo = idNo.substring(0, 6) + "19" + idNo.substring(6);
		// 加权因子
		int[] wi = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
		// 校验码
		String[] vi = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
		int sum = 0;
		for (int i = 0; i < idNo.length(); i++) {
			sum = sum + wi[i]
					* Integer.valueOf(idNo.substring(i, i + 1)).intValue();
		}
		int y = sum % 11;
		return idNo + vi[y];
	}

	/**
	 * 
	 * {取得身份证号上的出生日期}
	 * 
	 * @param idNo
	 *            15位或18位身份证号
	 * @return java.sql.Date 出生日期
	 * 
	 * @version 1.0
	 * @since 1.0
	 */
	public static Date getBirthday(String idNo) {
		String birthDay = "";
		if (idNo.length() == 15) {
			birthDay = "19" + idNo.substring(6, 8) + '-'
					+ idNo.substring(8, 10) + '-' + idNo.substring(10, 12);
		} else {
			birthDay = idNo.substring(6, 10) + '-' + idNo.substring(10, 12)
					+ '-' + idNo.substring(12, 14);
		}
		return Date.valueOf(birthDay);
	}

	/**
	 * 
	 * {比较两个日期的大小 .如果date1在date2之后，返回true; date1在date2之前或相等，返回false}
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 * 
	 * @version 1.0
	 * @since 1.0
	 */
	public static boolean dateCompare(Date date1, Date date2) {
		return date1.compareTo(date2) > 0 ? true : false;
	}

	/**
	 * 
	 * {身份证15位转18位}
	 * 
	 * @param IdNo
	 * @return
	 * 
	 * @version 1.0
	 * @since 1.0
	 * @note 上海银行提供的转换方法
	 */
	public static String convert15to18(String IdNo) {
		String sID15 = IdNo;
		String sID18 = "";
		String sTemp = "";
		if (sID15 == null || sID15.trim().length() != 15) {
			sID18 = "";
		} else {
			sID15 = sID15.trim();
			try {
				sTemp = sID15.substring(0, 6) + "19" + sID15.substring(6);
				sID18 = sTemp + getVerify(sTemp);
			} catch (Exception e) {
				sID18 = "";
			}
		}
		return sID18;
	}

	/**
	 * 
	 * {返回18位最后一位验证码}
	 * 
	 * @param s17
	 * @return
	 * @throws Exception
	 * 
	 * @version 1.0
	 * @since 1.0
	 * @note 上海银行提供的转换方法
	 */
	private static String getVerify(String s17) throws Exception {
		String sVerify = "";
		String code = "";
		int num = 0;
		int tmp = 0;
		for (int i = 18; i >= 2; i--) {
			num += (Math.pow(2, i - 1) % 11)
					* Integer.parseInt(s17.substring(18 - i, 18 - i + 1));
		}
		num %= 11;
		switch (num) {
		case 0:
			code = "1";
			break;
		case 1:
			code = "0";
			break;
		case 2:
			code = "X";
			break;
		default:
			tmp = 12 - num;
			code = Integer.toString(tmp);
			break;
		}
		sVerify = code;
		return sVerify;
	}
	

	
	/**
	 * 产生n位随机数
	 * 
	 * @param n
	 * @param radix
	 *            10-只有数字 36-包含数字和字母(小写)
	 * @return
	 */
	public static String randomPassword(int n, int radix) {
		SecureRandom a = new SecureRandom();
		long l = a.nextLong();
		long l1 = l < 0L ? -l : l;
		StringBuffer stringbuffer;
		for (stringbuffer = new StringBuffer(Long.toString(l1, radix)); stringbuffer
				.length() < n; stringbuffer.insert(0, '0'))
			;
		if (stringbuffer.length() > n)
			return stringbuffer.substring(stringbuffer.length() - n);
		else
			return stringbuffer.toString();
	}
	/**
	 * 判断字符串中是否包含字母
	 */
	public static boolean letterIsExit(String str) {
		if(str == null||"".equals(str))
			return false;
		String rex = ".*[a-zA-Z].*";
		if(str.matches(rex))
			return true;
		return false;
	}
	/**
	 * 产生N位随机数 其中包含数字和字母的组合含有大小写
	 * 
	 * @param n
	 * @return
	 */
//	public static String randomPassword2(int n) {
//		char[] constant = { '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
//				'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'p',
//				'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
//				'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
//				'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '2',
//				'3', '4', '5', '6', '7', '8', '9' };
//		StringBuilder newRandom = new StringBuilder(65);
//		Random rd = new Random();
//		for (int i = 0; i < n; i++) {
//			newRandom.append(constant[rd.nextInt(65)]);
//		}
//
//		return newRandom.toString();
//	}
	


	/**
	 * 组织机构代码格式化
	 * 
	 * @param orgCode
	 * 
	 * @author guojie
	 * 
	 */
	public static String formatOrgCode(String orgCode) {
		if (orgCode == null || orgCode.length() < 9) {
			return orgCode;
		}
		if (orgCode.substring(8, 9).equals("-")) {
			return orgCode;
		}

		return orgCode.substring(0, 8) + "-" + orgCode.substring(8);
	}
	
	/**
	 * 判断字符串是否是数字串
	 * @param num
	 * @return
	 */
	public static boolean isNumber(String num){
		if(num==null){
			return false;
		}
		for(int i=0;i<num.length();++i){
			char c=num.charAt(i);
			if(c<'0'||c>'9'){
				return false;
			}
		}
		return true;
	}
	
	public static java.util.Date rollDateByMinute(java.util.Date date,int minutes){
		Calendar calendar = GregorianCalendar.getInstance(Locale.getDefault());
		if (date != null) {
			calendar.setTime(date);
		}
		calendar.add(Calendar.MINUTE, minutes);
		return new java.util.Date(calendar.getTimeInMillis());
	}
	/**
	 * 判断是否为简单密码
      @author wangqi
	 */
	public static boolean checkSimplePwd(String pwd) {
		char[] charArray = pwd.toCharArray();
		String eq = "";
		String asc = "";
		String desc = "";
		for (int i = 0; i < charArray.length - 1; i++) {
			Character c1 = charArray[i];
			Character c2 = charArray[i + 1];
			if (c1.equals(c2)) {
				eq += "1";
				continue;
			}
			String s = c1.toString() + c2.toString();
			if (Pattern.compile("^\\d+$").matcher(s.toString()).matches()) {
				int i1 = Integer.valueOf(c1.toString());
				int i2 = Integer.valueOf(c2.toString());
				if (i1 - i2 == 1)
					desc += "1";
				else if (i2 - i1 == 1) {
					asc += "1";
				}
				else
					break;
			}
			else
				break;
		}
		if (eq.length() == pwd.length() - 1
				|| desc.length() == pwd.length() - 1
				|| asc.length() == pwd.length() - 1) {
			return false;
		}
		return true;
	}
	/**
	 * 判断个人USBKey编号有效性
      @author wangqi
	 */
	public static boolean checkPerUSBNo(String no){
		if(no.startsWith("CF"))
			return true;
		if(no.length()!=12)
			return false;
		if(!Pattern.compile("^\\d+$").matcher(no).matches())
			return false;
		int checkNo=Integer.valueOf(no.substring(6,7));
		String realNo=no.substring(0,6)+no.substring(7);
		char[] c=realNo.toCharArray();
	    int count=0;
		for(int i=c.length-1;i>=0;i--){
			int cc=Integer.valueOf(((Character)c[i]).toString());
			int jj=(c.length-i-1)%2==0?cc*2:cc;
			int kk=jj>=10?jj/10+jj%10:jj;
			count+=kk;
		}
		return (10-count%10)%10==checkNo;
	}
	
	/**
	 * 判断个人预制证书二代E盾编号有效性
      @author fubin
	 */
	public static boolean checkPerEDUSBNo(String no){
		//Step1:编号总长度为16个字符
		//Step2:判断前五位是否为95594
		//Step3:判断编号是否为数字
		//Step4:对第16位校验码进行校验
		if(no.length()!=16){
			return false;
		}
		if(!(no.startsWith("TZBANK") || no.startsWith("YZBANK"))){
			return false;
		}
//		if(!Pattern.compile("^\\d+$").matcher(no).matches()){
//			return false;
//		}
//	    String code = genCode(no); //校验码
//	    if(!code.equals(no.substring(15))){
//	    	return false;
//	    }
	    return true;
	}
	
	//校验位算法
	public static String genCode(String id) {
        char pszSrc[] = id.toCharArray();
        int iS = 0;
        int iW[] = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8 };
        char szVerCode[] = new char[] { '1', '0', '3', '9', '8', '7', '6', '5', '4', '3', '2' };
        int i;
        for (i = 0; i < 15; i++) {
            iS += (int) (pszSrc[i] - '0') * iW[i];
        }
        int iY = iS % 11;
        char[] aa = new char[1];
        aa[0] = szVerCode[iY];
        return new String(aa);
    }

	public static boolean checkEntUSBNo(String no){
		if(!no.startsWith("C"))
			return true;
		if(!no.startsWith("CO")&&!no.startsWith("C0"))
			return false;
		if(no.length()!=14&&no.length()!=13)
			return false;
		String realCompareNo="";
		if(no.length()==13)
			realCompareNo=no.substring(1);
		else if(no.length()==14)
			realCompareNo=no.substring(2);
		
		if(!Pattern.compile("^\\d+$").matcher(realCompareNo).matches())
			return false;
		int checkNo=Integer.valueOf(realCompareNo.substring(6,7));
		String realNo=realCompareNo.substring(0,6)+realCompareNo.substring(7);
		char[] c=realNo.toCharArray();
	    int count=0;
		for(int i=c.length-1;i>=0;i--){
			int cc=Integer.valueOf(((Character)c[i]).toString());
			int jj=(c.length-i-1)%2==0?cc*2:cc;
			int kk=jj>=10?jj/10+jj%10:jj;
			count+=kk;
		}
		return (10-count%10)%10==checkNo;
		
	}

	/**
	 * 
	 * 获取一个对象的string形式并去除空格
	 * 
	 * @param object
	 * @return
	 * 
	 * @version 1.0
	 * @since 1.0
	 */
	public static String toStringAndTrim(Object object) {
		if (object == null) {
			return "";
		} else {
			return object.toString().trim();
		}

	}

	/**
	 * 字符串替换,用replaceWith替换str中的replaced
	 * 
	 * @param str
	 * @param replaced
	 * @param replaceWith
	 * @return
	 */
	public static String replace(String str, String replaced, String replaceWith) {
		if (str == null) {
			return null;
		}
		if (replaced == null || replaceWith == null) {
			return str;
		}
		StringBuffer buf = new StringBuffer();

		int pos = str.indexOf(replaced);
		if (pos > -1) {
			String left = str.substring(0, pos);
			String right = str.substring(pos + replaced.length());
			if (right.length() < 2) {
				right = right + "0";
			}
			buf.append(left);
			buf.append(replaceWith);
			buf.append(replace(right, replaced, replaceWith));
		} else {
			buf.append(str);
		}

		return buf.toString();
	}
	
	/**
	 * 获取证书的签名算法 OID
	 * 
	 * @param cert
	 * @return
	 */
    public static String getSigAlgOID(Object cert)
    {
    	String sigAlgOid;
        if(cert instanceof X509Certificate)
        	sigAlgOid = ((X509Certificate)cert).getSigAlgOID();
        else
        	sigAlgOid = ((javax.security.cert.X509Certificate)cert).getSigAlgOID();
        
        return sigAlgOid;
    }
    public static String idTypeTransition(String oldIdType) {
        String newIdType="";//CFCA对应的证书类型编号
        if("00".equals(oldIdType)){//身份证
            newIdType="0";
        }else if("02".equals(oldIdType)){//户口本
            newIdType="E";
        }else if("05".equals(oldIdType)){//护照
            newIdType="1";
        }else if("03".equals(oldIdType)){//军官证、士兵证、军人证
            newIdType="2";
        }else if("06".equals(oldIdType)){//港澳通行证
            newIdType="B";
        }else if("07".equals(oldIdType)){//台湾通行证
            newIdType="C";
        }else if("01".equals(oldIdType)){//临时身份证
            newIdType="F";
        }else if("08".equals(oldIdType)){//外国人居住证
            newIdType="P";
        }else if("04".equals(oldIdType)){//警官证
            newIdType="G";
        }else if("20".equals(oldIdType)){//其他证件
            newIdType="Z";
        }else if("11".equals(oldIdType)){//组织机构代码证
            newIdType="7";
        }else if("17".equals(oldIdType)){//营业执照
            newIdType="8";
        }else if("18".equals(oldIdType)){//批文
            newIdType="M";
        }else if("19".equals(oldIdType)){//证明
            newIdType="Z";
        }else if("24".equals(oldIdType)){//五证合一证书
            newIdType="8";
        }else{
            newIdType="Z";
        }
        return newIdType;
    }
    
    /**
     *@author txm
     *@description 判断字符串，集合对象，对象数组内容是否为空
     *@return boolean
     */
    public static boolean isNullOrEmpty(Object obj){
		if (obj == null)
			return true;
		if (obj instanceof Collection){// 判断集合类型对象
			if (((Collection<?>)obj).isEmpty())
				return true;
		}
    	if (obj instanceof Map){// 判断Map类型对象
    		if (((Map<?, ?>)obj).isEmpty())
    			return true;
    	}
    	if (obj instanceof String){// 判断字符串类型对象
    		if (((String)obj).isEmpty())
    			return true;
    	}
    	if (obj instanceof Object[]){// 判断对象数组
    		if (((Object[])obj).length == 0)
    			return true;  		
    		for (Object tmp : (Object[])obj){
    			if (!isNullOrEmpty(tmp))
    				return false;
    		}
    		return true;
    	}
    	return false;
    }
    
    //1---安全强度低(纯数字、纯字母) 2---安全强度中(字母+数字、字母+特殊字符、数字+特殊字符) 3---安全强度高(纯特殊字符、字母+数字+特殊字符)
    public static String getPwdResult(String password) {
        
        Pattern p1 = Pattern.compile("\\d+|[a-zA-Z]+");
        Pattern p2 = Pattern.compile("([a-zA-Z]+[0-9]+)|([0-9]+[a-zA-Z]+)|([a-zA-Z]+[\\p{Punct}]+)|([\\p{Punct}]+[a-zA-Z]+)|([0-9]+[\\p{Punct}]+)|([\\p{Punct}]+[0-9]+)");
        Pattern p3 = Pattern.compile("[\\p{Punct}]+|([a-zA-Z]+[0-9]+[\\p{Punct}]+)|([a-zA-Z]+[\\p{Punct}]+[0-9]+)|([0-9]+[a-zA-Z]+[\\p{Punct}]+)|([0-9]+[\\p{Punct}]+[a-zA-Z]+)|([\\p{Punct}]+[a-zA-Z]+[0-9]+)|([\\p{Punct}]+[0-9]+[a-zA-Z]+)");
        
        Matcher m1 = p1.matcher(password);
        Matcher m2 = p2.matcher(password);
        Matcher m3 = p3.matcher(password);
        if(m1.matches()){
            return "1";
        }else if(m2.matches()){
            return "2";
        }else if(m3.matches()){
            return "3";
        }
        return "0";
    }
	public static void main(String[] arg) throws Exception{
		System.out.println(checkPerEDUSBNo("YZBANK1100000573"));
	}
}
